#include "precompiled/pchkrayserkraw.h"
#include "kraw/kraw3dinput.h"

#include "util/nstrlist.h"

ushort Kraw3DInput::keys[256];
float Kraw3DInput::mouse[Num_MouseEvents];
bool Kraw3DInput::buttons[Num_MouseButtons];

//-----------------------------------------------------------------------------

struct InputEvent
{
    EInputEvent eventType;
    uint key;
    union {
        uint value;
        bool state;
    };
};

//-----------------------------------------------------------------------------

void Kraw3DInput::OnKey( const uint key, const bool pressed )
{
    if (key < 2<<16) SetKey( key, pressed );
}

//-----------------------------------------------------------------------------

void Kraw3DInput::OnMouseMove( const int x, const int y )
{
    mouse[Mouse_Up] = y < 0 ? 1.f : 0;
    mouse[Mouse_Down] = y > 0 ? 1.f : 0;
    mouse[Mouse_Left] = x < 0 ? 1.f : 0;
    mouse[Mouse_Right] = x > 0 ? 1.f : 0;
}

//-----------------------------------------------------------------------------

void Kraw3DInput::OnMouseButton( const int /*x*/, const int /*y*/, const EMouseButton button, const bool pressed )
{
    buttons[button] = pressed;
}

//-----------------------------------------------------------------------------

void Kraw3DInput::SetKey( uint key, bool pressed )
{
    uint index = key>>4;
    uint flag = 1<<(key&0x0f);
    if (pressed)
        keys[index] |= flag;
    else
        keys[index] &= ~flag;
}

//-----------------------------------------------------------------------------

bool Kraw3DInput::GetKey( uint key )
{
    uint index = key>>4;
    uint flag = 1<<(key&0x0f);
    return (keys[index] & flag) != 0;
}

//-----------------------------------------------------------------------------

void Kraw3DInput::KeyEvent( const char* name, uint key, bool state )
{
    uint index = this->eventMap.AddString( name );
    InputEvent& event = this->inputEvents.At( index );
    event.eventType = Event_Key;
    event.key = key;
    event.state = state;
}

//-----------------------------------------------------------------------------

void Kraw3DInput::ButtonEvent( const char* name, EMouseButton key, bool state )
{
    uint index = this->eventMap.AddString( name );
    InputEvent& event = this->inputEvents.At( index );
    event.eventType = Event_Button;
    event.key = key;
    event.state = state;
}

//-----------------------------------------------------------------------------

void Kraw3DInput::MouseEvent( const char* name, EMouseEvent key )
{
    uint index = this->eventMap.AddString( name );
    InputEvent& event = this->inputEvents.At( index );
    event.eventType = Event_Mouse;
    event.key = key;
}

//-----------------------------------------------------------------------------

bool Kraw3DInput::GetState( const char* name )
{
    if ( this->eventMap.Exists( name ) )
    {
        InputEvent& event = this->inputEvents.At( this->eventMap[name] );
        switch ( event.eventType )
        {
        case Event_Key:
            return GetKey(event.key) == event.state;
        case Event_Button:
            return buttons[event.key] == event.state;
        }
    }

    return false;
}

//-----------------------------------------------------------------------------

float Kraw3DInput::GetValue( const char* name )
{
    if ( this->eventMap.Exists( name ) )
    {
        InputEvent& event = this->inputEvents.At( this->eventMap[name] );
        if ( event.eventType == Event_Mouse )
        {
            return mouse[event.key];
        }
    }

    return 0.f;
}

//-----------------------------------------------------------------------------

void Kraw3DInput::Tick( float /*fTime*/ )
{
    //update elapsed time
}
